// 导入我们需要执行操作的脚本集
import { expose } from 'http://192.168.87.19:8901/npm/comlink@4.3.1/dist/esm/comlink.mjs';
// import rhino3dm from 'http://192.168.87.19:8901/npm/rhino3dm@7.11.1/rhino3dm.module.js';
import JSZip from '../npm/jszip/dist/jszip.min.js';
import rhino3dm from '../npm/rhino3dm@7.11.1/rhino3dm.module.js';
import { Rhino3dmLoader } from '../npm/three/3DMLoader.js';
import { isString, isObject, loadFile } from './workerUtils.js';
// import rhino from "rhino"
const loader = new Rhino3dmLoader();
loader.setLibraryPath(`/npm/rhino3dm@7.11.1/`);
let self=window
async function getFrames (params = {}) {
	console.log('来自主线程的参数 params: ', params);

	self.rhino = await getRhino();
	// console.log('rhino: ', self.rhino);

	const objs = await jsonToThreeJsMesh(params);
	// console.log('objs: ', objs);

	return objs;
}

async function getRhino () {
	const Rhino3dm = rhino3dm;
	return new Rhino3dm({
		locateFile (path) {
			if (path.endsWith('.wasm')) {
				return '../npm/rhino3dm@7.11.1/rhino3dm.wasm';
			}
			return path;
		},
	}).then((rhino) => {
		console.log('rhino loaded!');
		return rhino;
	});
}

/**
 * json数据转换为 threeJs数据
 */
const jsonToThreeJsMesh = async (params) => {

	const objs = [];
	try {

		let doc;

		// clear doc
		if (doc !== undefined) {
			doc.delete();
		}

		const getRhinoObject = (jsonData) => {
			if (jsonData && isObject(jsonData)) {
				jsonData.version = Number(jsonData.version);
				jsonData.archive3dm = Number(jsonData.archive3dm);
				jsonData.opennurbs = Number(jsonData.opennurbs);
			}
			const rhinoObject = self.rhino.CommonObject.decode(jsonData);
			return rhinoObject;
		};

		let jsonDataList = [];
		if (params.decompress) {
			// zip解析并加载
			params.filePath = params.filePath.replace('.json', '.zip');
			const zipContent = await loadFile(params.filePath, 'arrayBuffer');
			jsonDataList = await unzip(zipContent);
		} else {
			jsonDataList = await loadFile(params.filePath, 'json');
		}

		if (!jsonDataList.length) {
			this.closeLoading();
			return objs;
		}

		const lineHandler = (rhinoObjects, objs) => {
			return new Promise(resolve => {

				doc = new self.rhino.File3dm();

				for (const rhinoObject of rhinoObjects) {
					if (rhinoObject !== null) {
						doc.objects().add(rhinoObject, null);
					}
				}

				if (doc.objects().count < 1) {
					console.error({ content: 'No objects to load!' });
					return;
				}

				const buffer = new Uint8Array(doc.toByteArray()).buffer;

				loader.parse(buffer, (object) => {
					// console.log('object: ', object);
					let lineIndex = 0;
					object.traverse((child) => {
						if (child.isMesh) {
							// objs.push(child);
							objs.push(child.toJSON());
						}
						if (child.isLine) {
							lineIndex++;
							const jsonData = jsonDataList[lineIndex - 1];
							child.linkName = jsonData ? jsonData.faceId : undefined;
							// objs.push(child);
							objs.push(child.toJSON());
						}
					}, false);

					// 关闭连接
					loader?.dispose?.();

					setTimeout(() => {
						doc.delete();
						doc = null;
					}, 300);

					return resolve(objs);
				});
			});
		};

		const rhinoObjects = [];
		for (const jsonData of jsonDataList) {
			const rhinoObject = getRhinoObject(jsonData);
			rhinoObjects.push(rhinoObject);
		}
		await lineHandler(rhinoObjects, objs);
	} catch (error) {
		console.error('rhinoJsonToThreeJsMesh error: ', error);
	}
	return objs;
};

/**
 * 读取压缩包的内容
 * @param zipData
 * @return {Promise<Array>}
 */
function unzip (zipData) {
	return new Promise(resolve => {
		const newZip = new JSZip();
		const checkCondition = (str) => !str.includes('__MACOSX') && !str.endsWith('/') && !str.includes('.DS_Store');
		newZip.loadAsync(zipData).then(zip => {
			zip.forEach((relativePath, zipEntry) => {
				if (checkCondition(relativePath) && relativePath.endsWith('.json')) {
					zipEntry.async('string').then(jsonStr => {
						let jsonDataList;
						if (isString(jsonStr)) {
							try {
								jsonDataList = (new Function('return ' + jsonStr))();
							} catch (e) {
								console.error('zip loadAsync err: ', e);
							}
						}
						resolve(jsonDataList);
					});
				}
			});
		});
	});
}

// expose the Analyzer "API" with Comlink
expose({
	getFrames,
});
